﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UtilZ.Dotnet.Ex.ZLog;

namespace UtilZ.Dotnet.DBIBase
{
    /// <summary>
    /// DbConnection连接池基类
    /// </summary>
    public abstract class DbConnectionPoolAbs : IDbConnectionPool
    {
        /// <summary>
        /// 数据库配置
        /// </summary>
        protected readonly DatabaseConfig _config;

        /// <summary>
        /// 数据库交互实例
        /// </summary>
        protected readonly IDBInteraction _interaction;

        /// <summary>
        /// 数据库读连接字符串
        /// </summary>
        protected readonly string _readConStr;

        /// <summary>
        /// 数据库写连接字符串
        /// </summary>
        protected readonly string _writeConStr;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="config">数据库配置</param>
        /// <param name="interaction">数据库交互实例</param>
        public DbConnectionPoolAbs(DatabaseConfig config, IDBInteraction interaction)
        {
            this._config = config;
            this._interaction = interaction;
            this._readConStr = this._interaction.GenerateDBConStr(config, DBVisitType.R);
            this._writeConStr = this._interaction.GenerateDBConStr(config, DBVisitType.W);
        }

        /// <summary>
        /// 获取数据库访问连接对象
        /// </summary>
        /// <param name="visitType">数据库访问类型</param>
        /// <returns>数据库访问连接对象</returns>
        public PrimitiveDbConnection GetDbConnection(DBVisitType visitType)
        {
            return this.PrimitiveGetDbConnection(visitType);
        }

        /// <summary>
        /// 获取数据库访问连接对象
        /// </summary>
        /// <param name="visitType">数据库访问类型</param>
        /// <returns>数据库访问连接对象</returns>
        protected abstract PrimitiveDbConnection PrimitiveGetDbConnection(DBVisitType visitType);




        /// <summary>
        /// 释放数据库访问连接对象
        /// </summary>
        /// <param name="con">数据库访问连接对象</param>
        /// <param name="visitType">数据库访问类型</param>
        public void ReleaseDbConnection(PrimitiveDbConnection con, DBVisitType visitType)
        {
            this.PrimitiveReleaseDbConnection(con, visitType);
        }

        /// <summary>
        /// 释放数据库访问连接对象
        /// </summary>
        /// <param name="con">数据库访问连接对象</param>
        /// <param name="visitType">数据库访问类型</param>
        protected abstract void PrimitiveReleaseDbConnection(PrimitiveDbConnection con, DBVisitType visitType);




        /// <summary>
        /// 重置连接
        /// </summary>
        public void ResetDbConnection()
        {
            this.PrimitiveResetDbConnection();
        }

        /// <summary>
        /// 重置连接
        /// </summary>
        protected abstract void PrimitiveResetDbConnection();



        /// <summary>
        /// 创建数据库连接对象
        /// </summary>
        /// <param name="visitType">DBVisitType</param>
        /// <param name="poolValidID">连接池标识</param>
        /// <returns></returns>
        protected PrimitiveDbConnection CreateConnection(DBVisitType visitType, int poolValidID)
        {
            DbProviderFactory dbProviderFactory = this._interaction.GetProviderFactory();
            var con = dbProviderFactory.CreateConnection();
            switch (visitType)
            {
                case DBVisitType.R:
                    con.ConnectionString = this._readConStr;
                    break;
                case DBVisitType.W:
                    con.ConnectionString = this._writeConStr;
                    break;
                default:
                    throw new NotImplementedException(visitType.ToString());
            }

            //con.ConnectionTimeout = config.ConnectionTimeout;,居然是只读的
            //con.Open();
            return new PrimitiveDbConnection(con, poolValidID);
        }




        #region IDispose接口实现
        private bool _disposed = false;
        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            try
            {
                if (this._disposed)
                {
                    return;
                }

                this.Dispose(true);
            }
            catch (Exception ex)
            {
                ZLoger.Error(ex);
            }
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        /// <param name="isDisposing">是否释放资源标识</param>
        protected virtual void Dispose(bool isDisposing)
        {
            try
            {

            }
            catch (Exception ex)
            {
                ZLoger.Error(ex);
            }
        }
        #endregion
    }
}
